﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Simulator;
using Statistics;

using ELW.Library.Math;
using ELW.Library.Math.Exceptions;
using ELW.Library.Math.Expressions;
using ELW.Library.Math.Tools;

namespace ModelConfigurator
{
    public partial class FormSource : FormBase
    {
        /// <summary>
        /// Редактируемый блок "Источник"
        /// </summary>
        public Source Edited { get; set; }

        public FormSource()
        {
            InitializeComponent();
        }


        private void FormSource_Load(object sender, EventArgs e)
        {

            //настроим текстовые поля
            try
            {
                textBoxC.Text = String.Format("{0}", ToolsHelper.Decompiler.Decompile(Edited.ComplexityCompiledString));
            }
            catch
            {
                errorProvider1.SetError(textBoxC, "Неверное выражение");
            }
            try
            {
                textBoxT.Text = String.Format("{0}", ToolsHelper.Decompiler.Decompile(Edited.TimeCompiledString));
            }
            catch
            {
                errorProvider1.SetError(textBoxT, "Неверное выражение");
            }

            try
            {
                textBoxQ.Text = String.Format("{0}", ToolsHelper.Decompiler.Decompile(Edited.QualityCompiledString));
            }
            catch
            {
                errorProvider1.SetError(textBoxQ, "Неверное выражение");
            }

            //настроим единицы измерения времени
            switch (Edited.SimulationTimeUnits)
            {
                case TimeUnits.days:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[0];
                    break;
                case TimeUnits.hours:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[1];
                    break;
                case TimeUnits.minutes:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[2];
                    break;
                default:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[3];
                    break;
            }
        }


        /// <summary>
        /// Проверка, является ли текст в текстовом поле числом типа Double. Если нет, выз. ErrorProvider
        /// </summary>
        /// <param name="txt">Текстовое поле</param>
        /// <returns>ИСТИНА если является double, иначе ЛОЖЬ</returns>
        private bool CheckDouble(TextBox txt)
        {
            string s = txt.Text;
            bool b = true;
            errorProvider1.Clear();
            try
            {
                Convert.ToDouble(s);
            }
            catch
            {
                b = false;
                errorProvider1.SetError((txt as Control), "В это текстовое поле можно ввести только число типа double");
            }
            return b;
            
        }

        private void textBoxDispC_TextChanged(object sender, EventArgs e)
        {
            //проверим, можно ли превратить текст в double
            CheckDouble((sender as TextBox));
        }

        private void textBoxTavr_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBoxDispT_TextChanged(object sender, EventArgs e)
        {
            //проверим, можно ли превратить текст в double
            CheckDouble((sender as TextBox));
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            if (Apply())//если без ошибки
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }//иначе не закрываем
                
        }
        /// <summary>
        /// Применить изменения к Edited
        /// </summary>
        private bool Apply(){
            
            //сначала проверим, везде ли верные выражения
            if (!txtCheck(textBoxC))
                return false;
            if (!txtCheck(textBoxT))
                return false;
            if (!txtCheck(textBoxQ))
                return false;
            //теперь настроим текстовые поля

            Edited.ComplexityString = textBoxC.Text;
            Edited.QualityString = textBoxQ.Text;
            Edited.TimeString = textBoxT.Text;

            return true;
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }

        private void textBoxC_Leave(object sender, EventArgs e)
        {
            if (txtCheck(textBoxC))
                Edited.ComplexityString = textBoxC.Text;
        }

        /// <summary>
        /// Проверка правильности выражения парсера
        /// </summary>
        /// <param name="txt">Текстовое поле</param>
        private bool txtCheck(TextBox txt)
        {
            errorProvider1.Clear();
            bool b = false;
            try
            {
                string s = txt.Text;
                //пробуем посчитать
                PreparedExpression preparedExpression = ToolsHelper.Parser.Parse(s);
                CompiledExpression ce = ToolsHelper.Compiler.Compile(preparedExpression);

                ToolsHelper.Calculator.Calculate(ce, new List<VariableValue>());
                b = true;
            }
            catch (CompilerSyntaxException ex)
            {
                errorProvider1.SetError(txt, String.Format("Ошибка компиляции: {0}", ex.Message));
            }
            catch (MathProcessorException ex)
            {
                errorProvider1.SetError(txt, String.Format("Ошибка: {0}", ex.Message));
            }
            catch (ArgumentException)
            {
                errorProvider1.SetError(txt, "Неверно введенные данные.");
            }
            catch (Exception)
            {
                errorProvider1.SetError(txt, "Непредвиденная ошибка.");
                throw;
            }
            return b;
        }

        private void textBoxT_Leave(object sender, EventArgs e)
        {
            if (txtCheck(textBoxT))
                Edited.TimeString = textBoxT.Text;
        }

        private void textBoxQ_Leave(object sender, EventArgs e)
        {
            if (txtCheck(textBoxQ))
                Edited.QualityString = textBoxQ.Text;
        }

        private void comboBoxTime_SelectedIndexChanged(object sender, EventArgs e)
        {
            //настроим единицы измерения времени
            switch (comboBoxTime.SelectedIndex)
            {
                case 0:
                    Edited.SimulationTimeUnits = TimeUnits.days;
                    break;
                case 1:
                    Edited.SimulationTimeUnits = TimeUnits.hours;
                    break;
                case 2:
                    Edited.SimulationTimeUnits = TimeUnits.minutes;
                    break;
                default:
                    Edited.SimulationTimeUnits = TimeUnits.seconds;
                    break;
            }
        }

        private void buttonHelp_Click(object sender, EventArgs e)
        {
            string openCHMFile = Application.StartupPath + "\\Справка SAPR-SIM.chm";
            try
            {
                if (!System.IO.File.Exists(openCHMFile))
                    System.IO.File.WriteAllBytes(openCHMFile, global::ModelConfigurator.Properties.Resources.Справка_SAPR_SIM);
            }
            catch
            {
                //если файл есть он не перепишется
            }
            helpProvider1.HelpNamespace = openCHMFile;
            Help.ShowHelp(this, this.helpProvider1.HelpNamespace, HelpNavigator.Topic, "module_2_6_3.htm");
        }
    }
}
